package cn.seaboot.admin.mvc.response;

import cn.seaboot.admin.mvc.Pagination;
import cn.seaboot.commons.core.Asserts;
import cn.seaboot.commons.core.CommonUtils;
import cn.seaboot.commons.exception.BizException;
import cn.seaboot.commons.lang.Null;
import com.github.pagehelper.PageHelper;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.mapping.ResultMapping;
import org.apache.ibatis.session.Configuration;

import java.util.Collection;
import java.util.List;

/**
 * @author Mr.css
 * @version 2024-12-09 8:54
 */
public class MybatisOrderMapper implements OrderMapper {

    /**
     * mybatis 配置信息
     */
    private final Configuration configuration;

    public MybatisOrderMapper(Configuration configuration) {
        this.configuration = configuration;
    }

    /**
     * 排序规则转换
     * <p>
     * 排序的格式是：[column] [desc/asc]，用的是真实数据库列名；
     * <p>
     * 这种写法，存在一定的 SQL 注入风险，而且，前端不一定能获取真实列名，因此，后台需要进行一次格式转换。
     * <p>
     * 当前函数，根据 mybatis 结果集配置，将字段名转换成数据库列名，安全级别较高。
     *
     * @param sort  排序字段
     * @param clazz 对象类型，用于寻找结果集配置
     */
    @Override
    public <T> String map(Class<T> clazz, String sort) {
        if (CommonUtils.isNotEmpty(sort)) {
            return Null.STRING;
        } else {
            String[] arr = sort.split(" ");

            ResultMap resultMap = getResultMap(clazz);
            Asserts.notNull(resultMap, "order-mapping is undefined: {}", clazz);

            List<ResultMapping> mappings = resultMap.getResultMappings();
            Asserts.notEmpty(mappings, "order-mapping is undefined: {}", clazz);

            String v;
            StringBuilder sb = new StringBuilder();
            for (String key : arr) {
                key = key.trim();
                if (!key.isEmpty()) {
                    if (key.equals("ascending")) {
                        // 升序排序
                        sb.append("ASC").append(" ");
                    } else if (key.equals("descending")) {
                        // 降序排序
                        sb.append("DESC").append(" ");
                    } else {
                        v = getMappingColumnName(mappings, key);
                        if (v != null) {
                            sb.append(v).append(" ");
                        } else {
                            throw new BizException("Illegal Argument: " + key);
                        }
                    }
                }
            }
            return sb.toString();
        }
    }

    /**
     * 根据字段名获取对应的数据库列名
     *
     * @param clazz 对象类型
     * @return 结果集配置
     */
    private ResultMap getResultMap(Class<?> clazz) {
        Collection<ResultMap> collection = configuration.getResultMaps();
        for (ResultMap resultMap : collection) {
            if (resultMap.getType() == clazz) {
                return resultMap;
            }
        }
        return null;
    }

    /**
     * 将驼峰式字段名，转换成数据库列名
     *
     * @param mappings 映射配置
     * @param field    字段名
     * @return 数据库列名
     */
    private String getMappingColumnName(List<ResultMapping> mappings, String field) {
        for (ResultMapping mapping : mappings) {
            if (field.equals(mapping.getProperty())) {
                return mapping.getColumn();
            }
        }
        return null;
    }
}
